package com.pingan.haofang.searchcloud.common.configuration;

import com.alibaba.druid.support.http.StatViewServlet;
import com.pingan.haofang.gov.sm.account.interceptor.AuthorizationInterceptor;
import com.pingan.haofang.searchcloud.common.constants.WebConstants;
import com.pingan.haofang.searchcloud.common.filters.ContextFilter;
import com.pingan.haofang.searchcloud.common.filters.MockSessionFilter;
import com.pingan.haofang.searchcloud.common.filters.SearchApiAuthorizationFilter;
import com.pingan.haofang.searchcloud.common.properties.DruidStatProperties;
import com.pingan.haofang.searchcloud.common.rpc.RPCFilter;
import com.pingan.haofang.searchcloud.index.service.ClusterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter;

import javax.servlet.DispatcherType;
import java.util.EnumSet;

/**
 * Spring Web配置类
 *
 * @author huhailiang
 * @date 2017/03/22
 */
@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {

	@Autowired
	private AuthorizationInterceptor authorizationInterceptor;

	@Autowired(required = false)
	private SearchApiAuthorizationFilter searchApiAuthorizationFilter;

	@Autowired
	private DruidStatProperties druidStatProperties;

	@Autowired
	private ClusterService clusterService;

	/**
	 * 拦截器配置
	 *
	 * @param registry 注册类
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(authorizationInterceptor).addPathPatterns(WebConstants.WEB_PREFIX + "/**",
				"/systemAdmin/**", "/modules/api/**");
		super.addInterceptors(registry);
	}

//    /**
//     * IKDicLoadListener
//     *
//     * @return
//     */
//    @Bean
//    public ServletListenerRegistrationBean<EventListener> getIKDicLoadListener() {
//        // 获取最前面一个Solr集群的分词数据，//TODO:假设以后要获取某个集群的就直接指定
//        String zk = clusterService.getClusterMap(EngineType.SOLR).values()
//                .stream().collect(Collectors.toList()).get(0).getHost();
//        DicLoadScheduler.zkHost = zk;
//        DicLoadScheduler dicLoadScheduler = new DicLoadScheduler();
//        ServletListenerRegistrationBean<EventListener> registrationBean
//                = new ServletListenerRegistrationBean<>();
//        registrationBean.setListener(dicLoadScheduler);
//        return registrationBean;
//    }

	/**
	 * 静态资源
	 *
	 * @param registry 注册类
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		// swagger
		registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
		registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
		registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

		// icon
		registry.addResourceHandler("favicon.ico").addResourceLocations("classpath:/META-INF/resources/");
		registry.addResourceHandler("/head/**").addResourceLocations("classpath:/head/");

		// 前端
		registry.addResourceHandler("index.html").addResourceLocations("classpath:/META-INF/resources/searchcloud/");
		registry.addResourceHandler("/static/**")
				.addResourceLocations("classpath:/META-INF/resources/searchcloud/static/");
		super.addResourceHandlers(registry);
	}

	@Bean
	public FilterRegistrationBean urlRewriteFilterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new UrlRewriteFilter());
		filterRegistrationBean.addUrlPatterns("/*");
		filterRegistrationBean.addInitParameter("modRewriteConfText",
				"RewriteRule  ^/$ /index.html\n" + "RewriteRule  ^/searchcloud(|/).*$ /index.html\n");
		filterRegistrationBean.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD));
		return filterRegistrationBean;
	}

	/**
	 * 请求上下文,应该在最外层
	 *
	 * @return
	 */
	@Bean
	public FilterRegistrationBean requestContextFilterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new ContextFilter());
		filterRegistrationBean.addUrlPatterns("/*");
		return filterRegistrationBean;
	}

	/**
	 * actuator允许跨域
	 */
	@Bean
	public FilterRegistrationBean corsFilterRegistrationBean(
			@Value("${management.context-path:/actuator}") String managementContextPath) {
		CorsConfiguration corsConfiguration = new CorsConfiguration();
		corsConfiguration.addAllowedHeader("*");
		corsConfiguration.addAllowedMethod("*");
		corsConfiguration.addAllowedOrigin("*");
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration(managementContextPath, corsConfiguration);
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new CorsFilter(source));
		filterRegistrationBean.addUrlPatterns(managementContextPath + "/*");
		return filterRegistrationBean;
	}

	/**
	 * 搜索API权限校验
	 *
	 * @return
	 */
	@Bean
	@ConditionalOnBean(value = SearchApiAuthorizationFilter.class)
	public FilterRegistrationBean searchApiAuthorizationFilterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(searchApiAuthorizationFilter);
		filterRegistrationBean.addUrlPatterns("/api/*");
		return filterRegistrationBean;
	}

	/**
	 * 请求上下文,应该在最外层
	 *
	 * @return
	 */
	@Bean
	@ConditionalOnBean(value = MockSessionFilter.class)
	public FilterRegistrationBean mockUserSessionFilterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(this.getApplicationContext().getBean(MockSessionFilter.class));
		filterRegistrationBean.addUrlPatterns("/web/*");
		return filterRegistrationBean;
	}

	/**
	 * RPC
	 *
	 * @return
	 */
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public FilterRegistrationBean rpcFilterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new RPCFilter());
		filterRegistrationBean.addUrlPatterns("/rpc");
		filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
		return filterRegistrationBean;
	}

	@Bean
	public ServletRegistrationBean druidServlet() {
		ServletRegistrationBean reg = new ServletRegistrationBean();
		reg.setServlet(new StatViewServlet());
		reg.addUrlMappings("/druid/*");
		reg.addInitParameter("loginUsername", druidStatProperties.getUsername());
		reg.addInitParameter("loginPassword", druidStatProperties.getPassword());
		return reg;
	}
}
